/**
 * Copyright (c) 2023 murenchao
 * taomu is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *       http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */
package cool.taomu.toolkit.utils

import cool.taomu.toolkit.utils.inter.ICallback
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.io.InputStream
import java.net.URL
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.nio.file.StandardCopyOption
import java.util.ArrayList
import java.util.List
import java.util.UUID
import java.util.Vector
import java.util.jar.JarEntry
import java.util.jar.JarInputStream
import java.util.jar.JarOutputStream
import java.util.regex.Matcher
import java.util.regex.Pattern
import org.apache.commons.io.FileUtils
import org.apache.commons.io.IOUtils
import org.eclipse.xtend.lib.annotations.Accessors
import org.slf4j.LoggerFactory

class FileTools {
	val static LOG = LoggerFactory.getLogger(FileTools)

	def static File createTempFile(String content) {
		var file = File.createTempFile("taomubox", ".tmp");
		FileUtils.writeStringToFile(file, content, "UTF-8");
		file
	}

	def static getSubdirectory(String baseDir, String fullDir, String separator) {
		var a = fullDir.trim.replace(baseDir.trim, "").replace(File.separator, separator);
		LOG.info("根目录:{},子目录:{}", baseDir, a);
		return a;
	}

	def static getSubdirectory(String baseDir, String fullDir) {
		var a = fullDir.trim.replace(baseDir.trim, "");
		LOG.info("根目录:{},子目录:{}", baseDir, a);
		return a;
	}

	def static scanner(String path, String suffix, ICallback<Path> ck) {
		var directoryPath = Paths.get(path); // 替换为你的目录路径  
		try {
			var walk = Files.walk(directoryPath).filter([Files.isRegularFile(it)])
			if (suffix !== null) {
				walk = walk.filter([it.toString.endsWith(suffix)])
			}
			walk.forEach([
				ck.call(it);
			]);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	def static fileDelete(Path tempDir) {
		Files.walk(tempDir).sorted([o1, o2|o2.compareTo(o1)]).map([it.toFile]).forEach([it.delete]);
	}

	def static scannerFile(String path, ICallback<File> ck) {
		var directoryPath = Paths.get(path); // 替换为你的目录路径  
		try {
			Files.walk(directoryPath).filter([Files.isRegularFile(it)]).forEach([
				ck.call(new File(it.toString));
			]);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	def static boolean isEmpty(String path) {
		var file = new File(path);
		var empty = true;
		// 检查文件是否存在  
		if (!file.exists()) {
			empty = true;
		} else if (file.length() == 0) {
			empty = true;
		} else {
			empty = false;
		}
		return empty;
	}

	def static List<String> scannDirFile(String path, String exclude) {
		val list = new ArrayList<String>()
		val dir = new File(path.trim)
		if (dir.isDirectory) {
			val files = dir.listFiles
			for (file : files) {
				if (file.isDirectory) {
					if (exclude !== null && !exclude.equals(file.getName())) {
						list.addAll(scannDirFile(file.absolutePath, exclude))
					} else {
						list.addAll(scannDirFile(file.absolutePath, exclude))
					}
				} else {
					var f = file.absolutePath
					LOG.info("扫描到的文件:{}", f);
					list.add(f)
				}
			}
		} else {
			list.add(dir.absolutePath)
		}
		return list
	}

	def static directoryTree(String path) {
		var root = new File(path);
		var dirList = new ArrayList<String>();
		// 检查路径是否有效且为目录  
		if (root.exists() && root.isDirectory()) {
			showDriectoryTree(root, 0, dirList);
		} else {
			dirList.add("无效的目录路径: " + path);
		}
		return dirList;
	}

	@Accessors
	static class JarFileEntity {
		var String namespace = "cool.taomu.toolkit.multi.script";
		var InputStream input;
		var String filename;

		new() {
		}
	}

	def static getJarUrl(String path) {
		return new URL(#["jar:file:", path, "!/"].join(""));
	}

	def static createJar(Vector<JarFileEntity> inputs, String jarFilePath) {
		var outPath = jarFilePath;
		if (!outPath.endsWith(".jar")) {
			outPath = #[outPath, "jar"].join(".")
		}
		try (var FileOutputStream fos = new FileOutputStream(jarFilePath)) {
			val JarOutputStream jos = new JarOutputStream(fos);
			inputs.forEach [
				var filename = it.filename === null ? UUID.randomUUID.toString.replace("-", "") : it.filename;
				var namespace = it.namespace !== null ? it.namespace.replace(".", "/") + "/" : "";
				var jarFile = #[namespace, filename].join("");
				var JarEntry je = new JarEntry(jarFile);
				try {
					jos.putNextEntry(je);
					IOUtils.copy(it.input, jos);
					if (it.input !== null) {
						it.input.close;
					}
					jos.closeEntry();
				} catch (IOException e) {
					e.printStackTrace();
				}
			]
			jos.close
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private def static void showDriectoryTree(File dir, int indent, List<String> res) {
		var indents = "  ";
		for (var i = 0; i < indent; i++) {
			indents += "  ";
		}
		res.add(#[indents, "|-- ", dir.getName()].join(""));
		var files = dir.listFiles();
		if (files !== null) {
			for (File file : files) {
				if (file.isDirectory()) {
					showDriectoryTree(file, indent + 1, res);
				} else {
					indents = "  ";
					for (var int i = 0; i < indent + 1; i++) {
						indents += "  ";
					}
					res.add(#[indents, "|-- ", file.getName()].join(""));
				}
			}
		}
	}

	def static String extractBetweenComments(String content, String startComment, String endComment) {
		// 构造正则表达式
		var String regex = Pattern.quote(startComment) + "(.*?)" + Pattern.quote(endComment);
		var Pattern pattern = Pattern.compile(regex, Pattern.DOTALL); // DOTALL 允许匹配换行符
		var Matcher matcher = pattern.matcher(content);

		if (matcher.find()) {
			// 返回匹配的内容（去掉首尾空白）
			return matcher.group(1).trim();
		} else {
			throw new IllegalArgumentException("No matching comments found in the content.");
		}
	}

	def static unpackWar(Class<?> zlass, List<String> unpackList) throws Exception {
		val URL warUrl = zlass.getProtectionDomain().getCodeSource().getLocation();
		val targetDir = new File(System.getProperty("user.dir"));
		LOG.info("war url:{} target Directory:{}", warUrl.path, targetDir)
		try (var jarStream = warUrl.openStream()) {
			val jarInputStream = new JarInputStream(jarStream);
			var JarEntry entry;
			while ((entry = jarInputStream.getNextJarEntry()) !== null) {
				val nentry = entry;
				unpackList.forEach [ unpack |
					if (nentry.name.startsWith(unpack)) {
						LOG.debug("需要解压的目录:{}\n,当前找到的目录:{}", unpackList, nentry.name)
						var entryFile = new File(targetDir, nentry.getName());
						if (nentry.isDirectory()) {
							entryFile.mkdirs();
						} else {
							entryFile.getParentFile().mkdirs();
							Files.copy(jarInputStream, entryFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
						}
					}
				]
			}
		}
	}
}
